home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_497 / windowshuffle / windowshuffle.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  21KB  |  684 lines

  1. /*
  2.  *  WindowShuffle.c
  3.  *
  4.  *  Commodity
  5.  *
  6.  *  Author: Stefan Sticht
  7.  *
  8.  *  Copyright: source is public domain, no copyright
  9.  *
  10.  *  Version history:
  11.  *
  12.  *  V1.00   initial release
  13.  *  V1.02   recompiled with main.c V1.02
  14.  *  V1.03   completly rewritten; shared commodity code thrown away; smaller, uses less CPU time
  15.  *  V1.04   now refuses to activate windows specified with REFUSE
  16.  *          second pair of hotkeys for only Activate without WindowToFront()
  17.  *          changed Priority to 21 to block out intuition for safety reasons
  18.  *  V1.05   some really minor changes
  19.  */
  20.  
  21. #define VERSION "V1.05"
  22.  
  23. /********************************************************************
  24.  *                             interfacing                          *
  25.  ********************************************************************/
  26.  
  27. /*
  28.  *  include files
  29.  */
  30.  
  31. #include <stdarg.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <intuition/intuitionbase.h>
  35. #include <libraries/commodities.h>
  36.  
  37. #include <clib/alib_protos.h>
  38. #include <clib/commodities_protos.h>
  39. #include <pragmas/commodities_pragmas.h>
  40. #include <clib/dos_protos.h>
  41. #include <pragmas/dos_pragmas.h>
  42. #include <clib/exec_protos.h>
  43. #include <pragmas/exec_pragmas.h>
  44. #include <clib/intuition_protos.h>
  45. #include <pragmas/intuition_pragmas.h>
  46.  
  47. #ifdef DEBUG
  48. #define printf KPrintF
  49. #include <clib/dlib_protos.h>
  50. #endif
  51.  
  52. /*
  53.  *  prototypes
  54.  */
  55. long request(char *title, char *gadgets, char *text, ...);
  56. struct Library *myopenlibrary(char *name, unsigned long version);
  57. struct Window *lastwindow(struct Window *win);
  58. struct Window *nextwindow(struct Window *win);
  59. struct Window *prevwindow(struct Window *win);
  60. void *retryallocmem(unsigned long size, long mode);
  61. void processmessages(void);
  62.  
  63. /*
  64.  *  global data defined in other moduls
  65.  *
  66.  *  libraries opened by startup code; basepointers needed by function pragmas
  67.  */
  68. extern struct Library *DOSBase;
  69. extern struct Library *SysBase;
  70.  
  71. /*
  72.  *  Disable SAS/C CTRL/C handling
  73.  */
  74. void chkabort(void) {}
  75.  
  76. /********************************************************************
  77.  *                             global data                          *
  78.  ********************************************************************/
  79.  
  80. #define TT_PREVAC  "PREV_ACTIVE"
  81. #define TT_NEXTAC  "NEXT_ACTIVE"
  82. #define TT_PREVBO  "PREV_BOTH"
  83. #define TT_NEXTBO  "NEXT_BOTH"
  84.  
  85. /*
  86.  *  definition of all messages (multi language support not completed yet)
  87.  */
  88. #ifdef GERMAN
  89.  
  90. #define RETRY_GADGETS           "Wiederholen|Abbrechen"
  91. #define RESUME_GADGETS          "Weiter"
  92. #define MSG_OUTOFMEM            "Leider ein Speicherblock von %ld bytes\nnicht alloziert werden!"
  93. #define MSG_LIBRARY_OPENERR     "Die %s (V%ld+) kann nicht geöffnet werden!"
  94. #define COM_NAME                "Fensterln"
  95. #define COM_DESCR               "Nächstes/letztes Fenster aktivieren"
  96. #define TT_BACKDROP             "BACKDROP"
  97. #define TT_NOWINTITLE           "OHNETITEL"
  98. #define TT_REFUSE               "DIESENICHT"
  99. #define MSG_REFUSE_TOO_COMPLEX  "Leider muß " TT_REFUSE " ignoriert werden,\nda der Ausdruck zu komplex ist."
  100. #define NO                      "NEIN"
  101. #define YES                     "JA"
  102.  
  103. #else
  104.  
  105. #define RETRY_GADGETS           "Retry|Cancel"
  106. #define RESUME_GADGETS          "Resume"
  107. #define MSG_OUTOFMEM            "Failure allocting %ld bytes of memory!"
  108. #define MSG_LIBRARY_OPENERR     "%s (V%ld+) can't be opened!"
  109. #define COM_NAME                "WindowShuffle"
  110. #define COM_DESCR               "Activate next/previous window"
  111. #define TT_BACKDROP             "BACKDROP"
  112. #define TT_NOWINTITLE           "WITHOUTTITLE"
  113. #define TT_REFUSE               "REFUSE"
  114. #define MSG_REFUSE_TOO_COMPLEX  TT_REFUSE " will be ignored\nas the pattern is too complex!"
  115. #define YES                     "YES"
  116. #define NO                      "NO"
  117.  
  118. #endif
  119.  
  120. #define COM_TITLE           COM_NAME " " VERSION
  121. #define CX_PRIORITY         "CX_PRIORITY"
  122. #define DEF_CX_PRIORITY     0
  123.  
  124. #define DEF_TT_PREVAC       "lcommand lshift j"
  125. #define DEF_TT_NEXTAC       "lcommand lshift k"
  126. #define DEF_TT_PREVBO       "lcommand j"
  127. #define DEF_TT_NEXTBO       "lcommand k"
  128. #define DEF_TT_BACKDROP     NO
  129. #define DEF_TT_NOWINTITLE   NO
  130. #define DEF_TT_REFUSE       ""
  131.  
  132. /*
  133.  *  data for cback.o
  134.  */
  135. long _stack = 4096l;
  136. char *_procname = COM_NAME;
  137. long _priority = 21l;
  138. long _BackGroundIO = 1;
  139. extern BPTR _Backstdout;
  140.  
  141. /*
  142.  *  library base pointers
  143.  */
  144. struct IntuitionBase *IntuitionBase;
  145. struct Library *CxBase;
  146. struct Library *IconBase;
  147.  
  148. /*
  149.  *  message port
  150.  */
  151. struct MsgPort *cxport = NULL;
  152.  
  153. /*
  154.  *  signal flag
  155.  */
  156. unsigned long cxsigflag = 0l;
  157.  
  158. /*
  159.  *  programtitle and version for Version command
  160.  */
  161. char versionstring[] ="\0$VER: " COM_NAME " " VERSION;
  162.  
  163. /*
  164.  *  helpstring
  165.  */
  166. #ifdef GERMAN
  167. char helpstring[] =
  168. "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) von Stefan Sticht\n"\
  169. "Aufruf: " COM_NAME " ["\
  170. CX_PRIORITY "=<n>] [" TT_NEXTAC "=<Aktion>] [" TT_PREVAC "=<Aktion>] ["\
  171. TT_NEXTBO "=<Aktion>] [" TT_PREVBO "=<Aktion>] [" TT_BACKDROP "=" YES "|" NO "] ["\
  172. TT_NOWINTITLE "=" YES "|" NO "] [" TT_REFUSE "=<Jokerausdruck>]\n";
  173. #else
  174. char helpstring[] =
  175. "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) by Stefan Sticht\n"
  176. "Usage: " COM_NAME " ["\
  177. CX_PRIORITY "=<n>] [" TT_NEXTAC "=<action>] [" TT_PREVAC "=<action>] ["\
  178. TT_NEXTBO "=<action>] [" TT_PREVBO "=<action>] [" TT_BACKDROP "=" YES "|" NO "] ["\
  179. TT_NOWINTITLE "=" YES "|" NO "] [" TT_REFUSE "=<wildcards>]\n";
  180. #endif
  181.  
  182. /*
  183.  *  the tooltypearray
  184.  */
  185. char **tooltypes;
  186.  
  187. /*
  188.  *  our broker
  189.  */
  190. CxObj *broker = NULL;
  191.  
  192. struct NewBroker newbroker = {
  193.     NB_VERSION,                         /* BYTE nb_Version               */
  194.     COM_NAME,                           /* BYTE *nb_Name                 */
  195.     COM_TITLE,                          /* BYTE *nb_Title                */
  196.     COM_DESCR,                          /* BYTE *nb_Descr                */
  197.     NBU_NOTIFY | NBU_UNIQUE,            /* SHORT nb_Unique               */
  198.     0,                                  /* SHORT nb_Flags                */
  199.     0,                                  /* BYTE nb_Pri                   */
  200.     NULL,                               /* struct MsgPort nb_Port        */
  201.     0                                   /* WORD nb_ReservedChannel       */
  202. };
  203.  
  204. #define NEXTAC  1
  205. #define PREVAC  2
  206. #define NEXTBO  3
  207. #define PREVBO  4
  208.  
  209. /*
  210.  *  pointer to refuse tokens
  211.  */
  212. char *refusetokens = NULL;
  213. /*
  214.  *  booleans for activation of backdrop windows and windows w/o title
  215.  */
  216. unsigned short backdrop;
  217. unsigned short nowintitle;
  218.  
  219. /********************************************************************
  220.  *                             functions                            *
  221.  ********************************************************************/
  222.  
  223. /*
  224.  *  request(): a glue routine to EasyRequest as simple as printf plus
  225.  *             titlestring, gadgettexts
  226.  *
  227.  *  Input: char *title:         pointer to the title of the requester
  228.  *         char *gadgets:       pointer to gadgettext
  229.  *         char *text:          text displayed in requester
  230.  *
  231.  *  Result: same as EasyrequestArgs()
  232.  *
  233.  * !!! for more info see EasyRequestArgs() in Autodocs/intuition.doc !!!
  234.  */
  235. long request(char *title, char *gadgets, char *text, ...)
  236. {
  237.     /*
  238.      *  structure textreq only needed in this function, so hide it here
  239.      *  must be static, in order to be initialized only once
  240.      */
  241.     static struct EasyStruct textreq = {
  242.         sizeof (struct EasyStruct), /* ULONG es_StructSize      */
  243.         0l,                         /* ULONG es_Flags           */
  244.         NULL,                       /* UBYTE *es_Title          */
  245.         NULL,                       /* UBYTE *es_TextFormat     */
  246.         NULL,                       /* UBYTE *es_GadgetFormat   */
  247.         };
  248.     va_list ap;
  249.     long rc;
  250.  
  251.     /*
  252.      *  get start of variable arguments
  253.      */
  254.     va_start(ap, text);
  255.  
  256.     /*
  257.      *  update textreq
  258.      */
  259.     textreq.es_Title = (UBYTE *)title;
  260.     textreq.es_TextFormat = (UBYTE *)text;
  261.     textreq.es_GadgetFormat = (UBYTE *)gadgets;
  262.  
  263.     /*
  264.      *  win may be NULL
  265.      */
  266.     rc = EasyRequestArgs(NULL, &textreq, NULL, ap);
  267.  
  268.     va_end(ap);
  269.  
  270.     return(rc);
  271. }
  272.  
  273. /*
  274.  *  myopenlibrary(): same as OpenLibrary(), but opens a retry-requester
  275.  *                   if OpenLibrary() fails, to give the user a chance to
  276.  *                   copy the library to libs: and retry
  277.  *                   requires request(), see above
  278.  */
  279. struct Library *myopenlibrary(char *name, unsigned long version)
  280. {
  281.     static char errortext[] = MSG_LIBRARY_OPENERR;
  282.     struct Library *libptr;
  283.     long ok = TRUE;
  284.  
  285.     do {
  286.         if (!(libptr = OpenLibrary((UBYTE *)name, version))) {
  287.             if (IntuitionBase) {
  288.                 ok = request(COM_NAME ":", RETRY_GADGETS, errortext, name, version);
  289.                 }
  290.             else ok = FALSE;
  291.             }
  292.         } while (!libptr && ok);
  293.  
  294.     #ifdef DEBUG
  295.     printf("myopenlibrary(%s, %ld) = 0x%lx\n", name, version, libptr);
  296.     #endif
  297.     return(libptr);
  298. }
  299.  
  300. void *retryallocmem(unsigned long size, long mode)
  301. {
  302.     void *addr;
  303.  
  304.     do {
  305.  
  306.         if (!(addr = AllocMem(size, mode))) {
  307.  
  308.             if (!(request(COM_NAME ":", RETRY_GADGETS, MSG_OUTOFMEM, size)))
  309.                 return(NULL);
  310.  
  311.             }
  312.  
  313.         } while (!addr);
  314.  
  315.     return(addr);
  316. }
  317.  
  318. void main(int argc, char *argv[])
  319. {
  320.     CxObj *nextacfilter = NULL;
  321.     CxObj *prevacfilter = NULL;
  322.     CxObj *nextbofilter = NULL;
  323.     CxObj *prevbofilter = NULL;
  324.     struct Message *msg;
  325.     char *refuse;
  326.     char *nextackey;
  327.     char *prevackey;
  328.     char *nextbokey;
  329.     char *prevbokey;
  330.     unsigned long size = 0l;
  331.  
  332.     if ((argc > 1) && (*argv[1] == '?')) {
  333.         /*
  334.          *  display help string
  335.          */
  336.         if (_Backstdout) {
  337.             Write(_Backstdout, helpstring, sizeof(helpstring) - 1l);
  338.             Close(_Backstdout);
  339.             }
  340.         return;
  341.         }
  342.     else if (argc && _Backstdout) Close(_Backstdout);
  343.  
  344.     /*
  345.      *  open required libraries first
  346.      */
  347.     if (IntuitionBase = (struct IntuitionBase *)myopenlibrary("intuition.library", 37l)) {
  348.  
  349.         if (CxBase = myopenlibrary("commodities.library", 37l)) {
  350.  
  351.             if (IconBase = myopenlibrary("icon.library", 37l)) {
  352.  
  353.                 /*
  354.                  * create tooltypes array (requires icon.library open!!!)
  355.                  */
  356.                 tooltypes = (char **)ArgArrayInit(argc, argv);
  357.  
  358.                 /*
  359.                  *  create our message port
  360.                  */
  361.                 if (cxport = CreateMsgPort()) {
  362.  
  363.                     cxsigflag = 1l << cxport->mp_SigBit;
  364.                     /*
  365.                      * set up some broker data
  366.                      */
  367.                     newbroker.nb_Pri = ArgInt(tooltypes, CX_PRIORITY, DEF_CX_PRIORITY);
  368.                     newbroker.nb_Port = cxport;
  369.  
  370.                     if (broker = CxBroker(&newbroker, NULL)) {
  371.  
  372.                         if ((nextackey = ArgString(tooltypes, TT_NEXTAC, DEF_TT_NEXTAC)) &&
  373.                             *nextackey) {
  374.  
  375.                             if (nextacfilter = HotKey(nextackey, cxport, NEXTAC))
  376.                                 AttachCxObj(broker, nextacfilter);
  377.  
  378.                             } /* if nextackey */
  379.  
  380.                         if ((prevackey = ArgString(tooltypes, TT_PREVAC, DEF_TT_PREVAC)) &&
  381.                             *prevackey) {
  382.  
  383.                             if (prevacfilter = HotKey(prevackey, cxport, PREVAC))
  384.                                 AttachCxObj(broker, prevacfilter);
  385.  
  386.                             } /* if prevackey */
  387.  
  388.                         if ((nextbokey = ArgString(tooltypes, TT_NEXTBO, DEF_TT_NEXTBO)) &&
  389.                             *nextbokey) {
  390.  
  391.                             if (nextbofilter = HotKey(nextbokey, cxport, NEXTBO))
  392.                                 AttachCxObj(broker, nextbofilter);
  393.  
  394.                             } /* if nextbokey */
  395.  
  396.                         if ((prevbokey = ArgString(tooltypes, TT_PREVBO, DEF_TT_PREVBO)) &&
  397.                             *prevbokey) {
  398.  
  399.                             if (prevbofilter = HotKey(prevbokey, cxport, PREVBO))
  400.                                 AttachCxObj(broker, prevbofilter);
  401.  
  402.                             } /* if prevbokey */
  403.  
  404.                         backdrop = (strcmpi((char *)ArgString(tooltypes, TT_BACKDROP, DEF_TT_BACKDROP),
  405.                                     YES)) ? FALSE : TRUE;
  406.  
  407.                         nowintitle = (strcmpi((char *)ArgString(tooltypes, TT_NOWINTITLE, DEF_TT_NOWINTITLE),
  408.                                     YES)) ? FALSE : TRUE;
  409.  
  410.                         refuse = (char *)ArgString(tooltypes, TT_REFUSE, DEF_TT_REFUSE);
  411.  
  412.                         #ifdef DEBUG
  413.                         if (refuse) printf("WindowShuffle: refuse = %s\n", refuse);
  414.                         #endif
  415.  
  416.                         if (*refuse && (size = (strlen(refuse) << 1)) &&
  417.                             (refusetokens = retryallocmem(size, 0l))) {
  418.  
  419.                             #ifdef DEBUG
  420.                             printf("WindowShuffle: size = %ld, refusetokens = 0x%lx\n", size, refusetokens);
  421.                             #endif
  422.  
  423.                             if (ParsePattern(refuse, refusetokens, size) == -1l)
  424.                                 request(COM_NAME ":", RESUME_GADGETS, MSG_REFUSE_TOO_COMPLEX);
  425.  
  426.                             #ifdef DEBUG
  427.                             printf("WindowShuffle: refusetokens = %s\n", refusetokens);
  428.                             #endif
  429.  
  430.                             }
  431.  
  432.                         if ((nextacfilter && !CxObjError(nextacfilter)) ||
  433.                             (prevacfilter && !CxObjError(prevacfilter)) ||
  434.                             (nextbofilter && !CxObjError(nextbofilter)) ||
  435.                             (prevbofilter && !CxObjError(prevbofilter))) {
  436.  
  437.                             /*
  438.                              *  activate our commodity
  439.                              */
  440.                             ActivateCxObj(broker, 1l);
  441.                             /*
  442.                              *  now watch our numerous ports
  443.                              */
  444.                             processmessages();
  445.  
  446.                             } /* if !CxObjError() */
  447.  
  448.                         DeleteCxObjAll(broker);
  449.  
  450.                         if (refusetokens) FreeMem(refusetokens, size);
  451.  
  452.                         } /* if broker */
  453.  
  454.                     #ifdef DEBUG
  455.                     else printf("main(): CxBroker() failed!\n");
  456.                     #endif
  457.  
  458.                     /*
  459.                      *  delete our message port after replying all pending messages
  460.                      */
  461.                     while (msg = GetMsg(cxport)) ReplyMsg(msg);
  462.                     DeleteMsgPort(cxport);
  463.                     } /* if cxport */
  464.  
  465.                 #ifdef DEBUG
  466.                 else printf("main(): CraeteMsgPort() failed!\n");
  467.                 #endif
  468.  
  469.                 ArgArrayDone();
  470.  
  471.                 CloseLibrary(IconBase);
  472.                 } /* if IconBase */
  473.  
  474.             CloseLibrary(CxBase);
  475.             } /* if CxBase */
  476.  
  477.     CloseLibrary((struct Library *)IntuitionBase);
  478.     } /* if IntuitionBase */
  479.  
  480. } /* main() */
  481.  
  482. #define PREV    1
  483. #define TOF     2
  484. #define AC      4
  485. #define BO      6
  486.  
  487. void processmessages(void)
  488. {
  489.     struct Window *win;
  490.     struct Message *msg;
  491.     unsigned long sigreceived;
  492.     unsigned long msgtype;
  493.     unsigned long msgid;
  494.     unsigned long lock;
  495.     unsigned short quit = FALSE;
  496.     unsigned char mode;
  497.  
  498.     while (!quit) {
  499.  
  500.         sigreceived = Wait(SIGBREAKF_CTRL_C | cxsigflag);
  501.  
  502.         #ifdef DEBUG
  503.         printf("processmessages(): signal received\n");
  504.         #endif
  505.  
  506.         if (sigreceived & SIGBREAKF_CTRL_C) quit = TRUE;
  507.  
  508.         if (sigreceived & cxsigflag) {
  509.  
  510.             while (msg = (struct Message *)GetMsg(cxport)) {
  511.  
  512.                 msgid = CxMsgID((CxMsg *)msg);
  513.                 msgtype = CxMsgType((CxMsg *)msg);
  514.  
  515.                 ReplyMsg(msg);
  516.  
  517.                 switch (msgtype) {
  518.  
  519.                     case CXM_IEVENT:
  520.                         mode = 0;
  521.                         switch (msgid) {
  522.  
  523.                             case PREVAC:    mode = PREV;
  524.                             case NEXTAC:    mode |= AC;
  525.                                             break;
  526.  
  527.                             case PREVBO:    mode = PREV;
  528.                             case NEXTBO:    mode |= BO;
  529.                                             break;
  530.  
  531.                             } /* switch msgid */
  532.  
  533.                         lock = LockIBase(0l);
  534.                         if (mode & PREV) {
  535.                             /*
  536.                              *  get previous window
  537.                              */
  538.                             if (!(win = prevwindow(IntuitionBase->ActiveWindow))) {
  539.                                 /*
  540.                                  *  no prev window; get last window;
  541.                                  *  if last window = backdrop || nowintitle ||
  542.                                  *  refusewindow get predecessor of lastwindow
  543.                                  */
  544.                                 if ((win = lastwindow(IntuitionBase->ActiveWindow)) &&
  545.                                     ((!backdrop && (win->Flags & WFLG_BACKDROP)) ||
  546.                                     (!nowintitle && !win->Title)) ||
  547.                                     (refusetokens && win->Title && MatchPattern(refusetokens, win->Title)))
  548.                                     win = prevwindow(win);
  549.                                     }
  550.                             }
  551.                         else {
  552.                             /*
  553.                              *  get next window
  554.                              */
  555.                             if (!(win = nextwindow(IntuitionBase->ActiveWindow))) {
  556.                                 /*
  557.                                  *  no next window; get first window;
  558.                                  *  if first window = backdrop || nowintitle ||
  559.                                  *  refusewindow get first window->NextWindow
  560.                                  */
  561.                                 if ((win = IntuitionBase->ActiveScreen->FirstWindow) &&
  562.                                     ((!backdrop && (win->Flags & WFLG_BACKDROP)) ||
  563.                                     (!nowintitle && !win->Title)) ||
  564.                                     (refusetokens && win->Title && MatchPattern(refusetokens, win->Title)))
  565.                                     win = nextwindow(win);
  566.                                 }
  567.                             }
  568.                         UnlockIBase(lock);
  569.  
  570.                         /*
  571.                          *  now activate and windowtofront the window if (win != NULL)
  572.                          */
  573.                         if (win) {
  574.  
  575.                             if ((mode & AC) && (win != IntuitionBase->ActiveWindow))
  576.                                 ActivateWindow(win);
  577.                             if ((mode & TOF) && (!(win->Flags & WFLG_BACKDROP)))
  578.                                 WindowToFront(win);
  579.  
  580.                             }
  581.                         break;
  582.  
  583.                     case CXM_COMMAND:
  584.                         switch (msgid) {
  585.  
  586.                             case CXCMD_UNIQUE:
  587.                             case CXCMD_KILL:
  588.                                 quit = TRUE;
  589.                                 break;
  590.  
  591.                             case CXCMD_DISABLE:
  592.                                 ActivateCxObj(broker, 0l);
  593.                                 break;
  594.  
  595.                             case CXCMD_ENABLE:
  596.                                 ActivateCxObj(broker, 1l);
  597.                                 break;
  598.  
  599.                             }
  600.                         break;
  601.  
  602.                     } /* switch msgtype */
  603.  
  604.                 } /* while CxMsg */
  605.  
  606.             } /* if (sigreceived & cxsigflag) */
  607.  
  608.         } /* while !quit */
  609.  
  610.     ActivateCxObj(broker, 0l);
  611. }
  612.  
  613. /*
  614.  *  commodity functions
  615.  */
  616.  
  617. /*
  618.  *  get next window
  619.  */
  620. struct Window *nextwindow(register struct Window *win)
  621. {
  622.     register struct Window *w = NULL;
  623.  
  624.     if (win) {
  625.  
  626.         while (!w && win->NextWindow) {
  627.  
  628.             w = win = win->NextWindow;
  629.  
  630.             if ((!backdrop && (w->Flags & WFLG_BACKDROP)) ||
  631.                 (!nowintitle && !w->Title) ||
  632.                 (refusetokens && w->Title && MatchPattern(refusetokens, w->Title)))
  633.                 w = NULL;
  634.  
  635.             } /* while !w */
  636.  
  637.         } /* if win */
  638.  
  639.     return(w);
  640. }
  641.  
  642. /*
  643.  *  get previous window
  644.  */
  645. struct Window *prevwindow(register struct Window *win)
  646. {
  647.     register struct Window *w = NULL;
  648.  
  649.     if (win) {
  650.  
  651.         while (!w && (win != win->WScreen->FirstWindow)) {
  652.  
  653.             for (w = win->WScreen->FirstWindow; w->NextWindow != win; w = w->NextWindow);
  654.  
  655.             if ((!backdrop && (w->Flags & WFLG_BACKDROP)) ||
  656.                 (!nowintitle && !w->Title) ||
  657.                 (refusetokens && w->Title && MatchPattern(refusetokens, w->Title))) {
  658.  
  659.                 win = w;
  660.                 w = NULL;
  661.  
  662.                 }
  663.  
  664.             } /* while !w */
  665.  
  666.         } /* if win */
  667.  
  668.     return(w);
  669. }
  670.  
  671. /*
  672.  *  get last window
  673.  */
  674. struct Window *lastwindow(register struct Window *win)
  675. {
  676.     if (win) {
  677.  
  678.         while (win->NextWindow) win = win->NextWindow;
  679.  
  680.         } /* if win */
  681.  
  682.     return(win);
  683. }
  684.